﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SharpSoft.Geometries.Bezier
{

    public static class Bezier
    {
        /// <summary>
        /// 绘制n阶贝塞尔曲线路径
        /// </summary>
        /// <param name="points">输入点</param> 
        /// <param name="step">步长,步长越小，轨迹点越密集</param>
        /// <returns></returns>
        public static Point2D[] bezier_curves(Point2D[] points, float step)
        {
            var count = points.Length;
            List<Point2D> bezier_curves_points = new List<Point2D>();
            float t = 0F;
            do
            {
                Point2D temp_point = bezier_interpolation_func(t, points);    // 计算插值点
                t += step;
                bezier_curves_points.Add(temp_point);
            }
            while (t <= 1 && count > 1);    // 一个点的情况直接跳出.
            return bezier_curves_points.ToArray();  // 曲线轨迹上的所有坐标点
        }

        /// <summary>
        /// 计算插值点
        /// </summary>
        /// <param name="t"></param>
        /// <param name="points"></param>
        /// <returns></returns>
        public static Point2D bezier_interpolation_func(float t, Point2D[] points)
        {
            if (points.Length < 1)  // 一个点都没有
                throw new ArgumentOutOfRangeException();

            var count = points.Length;
            Point2D[] tmp_points = new Point2D[count];
            for (int i = 1; i < count; ++i)
            {
                for (int j = 0; j < count - i; ++j)
                {
                    if (i == 1) // 计算+搬运数据,在计算的时候不要污染源数据
                    {
                        tmp_points[j].X = (float)(points[j].X * (1 - t) + points[j + 1].X * t);
                        tmp_points[j].Y = (float)(points[j].Y * (1 - t) + points[j + 1].Y * t);
                        continue;
                    }
                    tmp_points[j].X = (float)(tmp_points[j].X * (1 - t) + tmp_points[j + 1].X * t);
                    tmp_points[j].Y = (float)(tmp_points[j].Y * (1 - t) + tmp_points[j + 1].Y * t);
                }
            }
            return tmp_points[0];
        }

    }
}
